package analyser.node.v2;

import analyser.node.AbstractNodeAnalyser;
import kit.AnalyserIndexerKit;
import kit.LetterIndexer;
import model.v2.conf.MibModuleComplianceNodeV2;
import util.common.CharType;
import util.common.CharTypeChecker;
import util.common.MibKeys;
import util.common.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class MibModuleComplianceV2Analyser extends AbstractNodeAnalyser<MibModuleComplianceNodeV2> {
    protected MibModuleComplianceNodeV2 node2;

    public MibModuleComplianceV2Analyser(List<String> txtList) {
        super(txtList);
        node2 = node = new MibModuleComplianceNodeV2();
    }

    @Override
    protected void doAnalyse() {
        int state = 1;
        int next;
        int fail;
        String str = null;
        while (state != 99){
            switch (state){
                case 1: //节点名
                    str = indexer.getNextIgnoreLeftSpace(CharType.Letter, CharType.Number, CharType.Hyphen);
                    if ((state = kit.notNull(str, 2, -state)) == 2){
                        node2.name = str;
                    }
                    break;
                case 2: //
                    state = kit.nextMatch(MibKeys.MODULE_COMPLIANCE, 3, -state);
                    break;
                case 3: //STATUS
                    next = state + 1;
                    fail = -state;
                    if ((state = kit.nextMatch(MibKeys.STATUS, next, fail)) == next){
                        str = indexer.getNextIgnoreLeftSpace(CharType.Letter);
                        if ((state = kit.notNull(str, next, fail)) == next){
                            node2.status = str;
                        }
                    }
                    break;
                case 4: //DESCRIPTION
                    next = state + 1;
                    fail = -state;
                    if ((state = kit.nextMatch(MibKeys.DESCRIPTION, next, fail)) == next){
                        str = extractAndAnalyseFormatText();
                        node2.description = str;
                    }
                    break;
                case 5: // REFERENCE
                    if (indexer.isNextMatchIgnoreLeftSpace(MibKeys.REFERENCE)){
                        str = extractAndAnalyseFormatText();
                        node2.reference = str;
                    }
                    state = 6;
                    break;
                case 6: //
                    str = indexer.probeNext(CharType.Letter);
                    state = StringUtils.isEquals(str, MibKeys.MODULE) ? 7 : 9;
                    break;
                case 7: //
                    if (node2.modules == null)
                        node2.modules = new ArrayList<>();
                    node2.modules.add(doAnalyseModule());
                    state = 8;
                    break;
                case 8: //
                    state = 6;
                    break;
                case 9: //
                    state = 10;
                    break;
                case 10:
                    if ((state = kit.nextMatch(MibKeys.ASSIGNMENT, 99, -10)) == 99){
                        this.analyseLeaf();
                    }
                    break;
                default:
                    kit.ThrowAnalysisException("节点MODULE-COMPLIANCE解析失败。", state, str);
            }
        }
        return;
    }

    private MibModuleComplianceNodeV2.Module doAnalyseModule() {
        MibModuleComplianceNodeV2.Module module = new MibModuleComplianceNodeV2.Module();
        module.compliances = new ArrayList<>();
        String str = null;
        String moduleName = null;
        int state = 1;
        while (state != 99){
            switch (state){
                case 1:
                    state = kit.nextMatch(MibKeys.MODULE, 2, -state);
                    break;
                case 2: // MANDATORY_GROUPS or OBJECT or GROUP or 类型
                    if (indexer.isNextMatchIgnoreLeftSpace(MibKeys.MANDATORY_GROUPS)){
                        if ((state = kit.nextMatch("{", 5, -2)) == 5){
                            module.mandatoryGroups = new ArrayList<>();
                        }
                        break;
                    }
                    str = indexer.probeNextIgnoreLeftSpace(CharType.Letter, CharType.Number, CharType.Number);
                    if (StringUtils.isEquals(str, MibKeys.OBJECT) && StringUtils.isEquals(str, MibKeys.GROUP)){
                        state = 8;
                    }else if (moduleName == null){
                        node2.moduleName = str = indexer.getNextIgnoreLeftSpace(CharType.Letter, CharType.Number, CharType.Number);
                        if ((state = kit.notNull(str, 3, -2)) == 3);
                    }else {
                        state = -2;
                    }
                    break;
                case 3: // { or (
                    char c = indexer.probeNextCharIgnoreLeftSpace();
                    if (CharTypeChecker.isSmallLetter(c)){
                        indexer.getNextIgnoreLeftSpace(CharType.Number, CharType.Letter, CharType.Hyphen);
                    }
                    state = 4;
                    break;
                case 4:
                    state = 2;
                    break;
                case 5: // , or {
                    str = indexer.getNextIgnoreLeftSpace(CharType.Letter, CharType.Number, CharType.Hyphen);
                    if ((state = kit.notNull(str, 6, -5)) == 6){
                        module.mandatoryGroups.add(str);
                    }
                    break;
                case 6:
                    if ((state = kit.nextMatch(",", 5, -6)) == -6){
                        state = kit.nextMatch("}", 7, -6);
                    }
                    break;
                case 7:
                    state = 8;
                    break;
                case 8:
                    str = indexer.probeNextIgnoreLeftSpace(CharType.Letter);
                    if (StringUtils.isEquals(str, MibKeys.OBJECT)){
                        state = 11;
                    }else if (StringUtils.isEquals(str, MibKeys.GROUP)){
                        state = 9;
                    }else {
                        state = 99;
                    }
                    break;
                case 9:
                    module.compliances.add(doAnalyseComplianceGroup());
                    state = 10;
                    break;
                case 10:
                    state = 8;
                    break;
                case 11:
                    module.compliances.add(doAnalyseObject());
                    state = 12;
                    break;
                case 12:
                    state = 8;
                    break;
                default:
                    kit.ThrowAnalysisException("节点MODULE-COMPLIANCE的Module模块解析失败。", state, str);
            }
        }
        return module;
    }

    private MibModuleComplianceNodeV2.Module.Compliance doAnalyseComplianceGroup() {
        MibModuleComplianceNodeV2.Module.Compliance compliance = new MibModuleComplianceNodeV2.Module.Compliance();
        String str = null;
        int state = 1;
        while (state != 99){
            switch (state){
                case 1:
                    state = kit.nextMatch(MibKeys.GROUP, 2, -1);
                case 2: // 类型 or SEQUENCE OF
                    str = indexer.getNextIgnoreLeftSpace(CharType.Letter, CharType.Number, CharType.Number);
                    if ((state = kit.notNull(str, 3, -2)) > 0){
                        compliance.group = str;
                    }
                    break;
                case 3: // { or (
                    if((state = kit.nextMatch(MibKeys.DESCRIPTION, 99, -3)) > 0){
                        compliance.description = str = extractAndAnalyseFormatText();
                    }
                    break;
                default:
                    kit.ThrowAnalysisException("节点MODULE-COMPLIANCE的ComplianceGroup模块解析失败。", state, str);
            }
        }
        return compliance;
    }

    private MibModuleComplianceNodeV2.Module.Compliance doAnalyseObject() {
        MibModuleComplianceNodeV2.Module.Compliance compliance = new MibModuleComplianceNodeV2.Module.Compliance();
        String str = null;
        int state = 1;
        while (state != 99){
            switch (state){
                case 1:
                    state = kit.nextMatch(MibKeys.OBJECT, 2, -1);
                    break;
                case 2: //
                    str = indexer.getNextIgnoreLeftSpace(CharType.Letter, CharType.Number, CharType.Number);
                    if ((state = kit.notNull(str, 3, -2)) > 0){
                        compliance.object = str;
                    }
                    break;
                case 3: //
                    if(indexer.isNextMatchIgnoreLeftSpace(MibKeys.SYNTAX)){
                        state = analyseSyntax(compliance,4,-3);
                    }else{
                        state = 4;
                    }
                    break;
                case 4: //
                    if(indexer.isNextMatchIgnoreLeftSpace(MibKeys.WRITE_SYNTAX)){
                        state = analyseSyntax(compliance,5,-4);
                        compliance.writeSyntax = compliance.syntax;
                        compliance.syntax = null;
                    }else {
                        state = 5;
                    }
                    break;
                case 5:
                    if(indexer.isNextMatchIgnoreLeftSpace(MibKeys.MIN_ACCESS)){
                        str = indexer.getNextIgnoreLeftSpace(CharType.Letter, CharType.Hyphen);
                        if ((state = kit.notNull(str, 6, -5)) > 0){
                            compliance.minAccess = str;
                        }
                    }
                    state = 6;
                    break;
                case 6:
                    if((state = kit.nextMatch(MibKeys.DESCRIPTION, 99, -6)) > 0){
                        compliance.description = str = extractAndAnalyseFormatText();
                    }
                    break;
                default:
                    kit.ThrowAnalysisException("节点MODULE-COMPLIANCE的ComplianceGroup模块解析失败。", state, str);
            }
        }
        return compliance;
    }

    private int  analyseSyntax(MibModuleComplianceNodeV2.Module.Compliance compliance, int success, int fail) {
        LetterIndexer indexer = this.kit.getIndexer();
        String str = null;
        String identify;
        int state = 2;
        while (state != 99){
            switch (state){
                case 1:
                    state = kit.nextMatch(MibKeys.SYNTAX, 2, fail);
                    break;
                case 2: // 类型 or SEQUENCE OF
                    str = kit.matchSyntaxType();
                    if (str == null)
                        str = indexer.getNextIgnoreLeftSpace(CharType.Number, CharType.Letter);
                    if ((state = kit.notNull(str, 3, fail)) == 3){
                        if (str.equals(MibKeys.SEQUENCE)){
                            state = kit.nextMatch(MibKeys.OF, 9, fail);
                        }else if(str.equals(MibKeys.OBJECT)){
                            state = kit.nextMatch(MibKeys.IDENTIFIER, 12, fail);
                        }else{
                            compliance.syntax = str;
                        }
                    }
                    break;
                case 3: // { or (
                    if((state = kit.nextMatch("{", 4, fail)) == 4){
                        compliance.namedBits = new ArrayList<>();
                    }else{
                        state = kit.nextMatch("(", 7, 11);
                    }
                    break;
                case 4:
                    int next = 5;
                    identify = str = indexer.getNextIgnoreLeftSpace(CharType.Letter, CharType.Number, CharType.Hyphen);
                    if((state = kit.notNull(str, next, fail)) == next &&
                            (state = kit.nextMatch("(", next, fail)) == next){
                        str = indexer.getNextIgnoreLeftSpace(CharType.Number, CharType.Hyphen);
                        if ((state = kit.notNull(str, next, fail)) == next){
                            int num = StringUtils.toInteger(str);
                            compliance.namedBits.add(new MibModuleComplianceNodeV2.Module.Compliance.NamedBit(identify, num));
                            state = kit.nextMatch(")", next, fail);
                        }
                    }
                    break;
                case 5: // , or {
                    if ((state = kit.nextMatch("}", 6, fail)) == fail){
                        state = kit.nextMatch(",", 4, fail);
                    }
                    break;
                case 6:
                    state = 99;
                    break;
                case 7:
                    int counter = 1;
                    char c;
                    while(counter > 0){
                        c = indexer.getNextChar();
                        if (c == '(')
                            counter++;
                        else if (c == ')')
                            counter --;
                    }
                    state = 8;
                    break;
                case 8:
                    state = 11;
                    break;
                case 9:
                    str = indexer.getNextIgnoreLeftSpace(CharType.Hyphen, CharType.Letter, CharType.Number);
                    if ((state = kit.notNull(str, 10, fail)) == 10){
                        compliance.syntax = MibKeys.OBJECT + " " + MibKeys.IDENTIFIER + " " + str;
                    }
                    break;
                case 10:
                    state = 11;
                    break;
                case 11:
                    state = 99;
                    break;
                case 12:
                    state = 11;
                    break;
                default:
                    return fail;
            }
        }
        return success;
    }
}
